﻿using AIStudio.Util.Primitives;
using Newtonsoft.Json;
using SuperSocket.ClientEngine;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using WebSocket4Net;

namespace AIStudio.WeChat.Client
{
    public class WSocketClient : IWSocketClient
    {

        #region 向外传递数据事件
        public event Action<WSMessageType, string> MessageReceived;
        #endregion

        WebSocket4Net.WebSocket _webSocket;
        /// <summary>
        /// 检查重连线程
        /// </summary>
        Thread _thread;
        bool _isRunning = true;
        /// <summary>
        /// WebSocket连接地址
        /// </summary>
        public string ServerPath { get; set; }

        public WSocketClient(string serverip, string url)
        {
            Init(serverip, url);
        }

        public WSocketClient()
        {

        }

        private void Init(string serverip, string url)
        {
            ServerIP = serverip;
            ServerPath = url;

            if (_webSocket != null)
            {
                Dispose();
            }
            this._webSocket = new WebSocket4Net.WebSocket(url);
            this._webSocket.Opened -= WebSocket_Opened;
            this._webSocket.Opened += WebSocket_Opened;
            this._webSocket.Error -= WebSocket_Error;
            this._webSocket.Error += WebSocket_Error;
            this._webSocket.Closed -= WebSocket_Closed;
            this._webSocket.Closed += WebSocket_Closed;
            this._webSocket.MessageReceived -= WebSocket_MessageReceived;
            this._webSocket.MessageReceived += WebSocket_MessageReceived;
            IsInit = true;

        }

        public void InitAndStart(string serverip, string url)
        {
            Init(serverip, url);
            Start();
        }

        #region "web socket "
        /// <summary>
        /// 连接方法
        /// <returns></returns>
        public bool Start()
        {
            bool result = true;
            try
            {
                this._webSocket.Open();

                this._isRunning = true;
                this._thread = new Thread(new ThreadStart(CheckConnection));
                this._thread.Start();
            }
            catch (Exception ex)
            {
                //_logger.Error(LogType.WebSocket, ex.ToString());
                result = false;
            }
            return result;
        }
        /// <summary>
        /// 消息收到事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            //_logger.Info(LogType.WebSocket, " Received:" + e.Message);

            var result = JsonConvert.DeserializeObject<MessageResult>(e.Message);

            MessageReceived?.Invoke(result.MessageType, (result.Data ?? "").ToString());
        }
        /// <summary>
        /// Socket关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Closed(object sender, EventArgs e)
        {
            //_logger.Info(LogType.WebSocket, "websocket_Closed");
        }
        /// <summary>
        /// Socket报错事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Error(object sender, ErrorEventArgs e)
        {
            //_logger.Info(LogType.WebSocket, "websocket_Error:" + e.Exception.ToString());
        }
        /// <summary>
        /// Socket打开事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Opened(object sender, EventArgs e)
        {
            //_logger.Info(LogType.WebSocket, " websocket_Opened");
        }
        /// <summary>
        /// 检查重连线程
        /// </summary>
        private void CheckConnection()
        {
            do
            {
                try
                {
                    IsConnected = true;
                    if (this._webSocket.State != WebSocket4Net.WebSocketState.Open && this._webSocket.State != WebSocket4Net.WebSocketState.Connecting)
                    {
                       // _logger.Info(LogType.WebSocket, " Reconnect websocket WebSocketState:" + this._webSocket.State);
                        this._webSocket.Close();
                        this._webSocket.Open();
                        Console.WriteLine("正在重连");

                        IsConnected = false;
                    }
                }
                catch (Exception ex)
                {
                    //_logger.Error(LogType.WebSocket, ex.ToString());
                }
                System.Threading.Thread.Sleep(1000);

            } while (this._isRunning);
        }
        #endregion

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="Message"></param>
        public void SendMessage(string Message)
        {
            Task.Factory.StartNew(() =>
            {
                if (_webSocket != null && _webSocket.State == WebSocket4Net.WebSocketState.Open)
                {
                    this._webSocket.Send(Message);
                }
            });
        }

        public void Dispose()
        {
            this._isRunning = false;
            try
            {
                if (_thread != null)
                {
                    _thread.Abort();
                }
            }
            catch
            {

            }

            if (this._webSocket != null)
            {
                this._webSocket.Close();
                this._webSocket.Dispose();
                this._webSocket = null;
            }
        }

        private bool _isinit;
        public bool IsInit
        {
            get { return _isinit; }
            set
            {
                _isinit = value;
            }
        }

        private bool _isConnected = true;
        public bool IsConnected
        {
            get { return _isConnected; }
            set
            {
               _isConnected = value;
            }
        }


        private string _serverIP;
        public string ServerIP
        {
            get { return _serverIP; }
            set
            {
               _serverIP =value;
            }
        }
       
    }
}
